#include "correction.h"
#include <cmath>

Correction::Correction(PNM* img) :
    Transformation(img)
{
}

Correction::Correction(PNM* img, ImageViewer* iv) :
    Transformation(img, iv)
{
}

PNM* Correction::transform()
{
    double shift  = getParameter("shift").toDouble();
    double factor = getParameter("factor").toDouble();
    double gamma  = getParameter("gamma").toDouble();

    int width  = image->width();
    int height = image->height();

    PNM* newImage = new PNM(width, height, image->format());

    if (image->format() == QImage::Format_Indexed8)
    {
		for (int x=0; x<width; x++)
			for (int y=0; y<height; y++)
			{
				QRgb pixel = image->pixel(x,y);
				int newColor(
					power(  mult(  add(qGray(pixel), shift),   factor),   gamma)
				);
				
				newImage->setPixel(x, y, newColor);
			}
    }
    else //if (image->format() == QImage::Format_RGB32)
    {
		for (int x=0; x<width; x++)
			for (int y=0; y<height; y++)
			{
				QRgb pixel = image->pixel(x,y);
				QColor newColor(
					power(  mult(  add(qRed(pixel), shift),   factor),   gamma),
					power(  mult(  add(qGreen(pixel), shift),   factor),   gamma),
					power(  mult(  add(qBlue(pixel), shift),   factor),   gamma)
				);
				
				newImage->setPixel(x,y,newColor.rgb());
			}
    }

    return newImage;
}

const int Correction::add(double value, double shift)
{
	return max(min((int)(value + shift), PIXEL_VAL_MAX), PIXEL_VAL_MIN);
}

const double Correction::mult(int value, double factor)
{
	return max(min((int)(value * factor), PIXEL_VAL_MAX), PIXEL_VAL_MIN);
}

const int Correction::power(int value, double power)
{
	return max(min((int)pow(value, power), PIXEL_VAL_MAX), PIXEL_VAL_MIN);
}
